package gateway.config.security.login;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSONObject;
import common.util.MultiReadHttpServletRequest;
import common.util.SecurityConstants;
import gateway.config.security.util.StopWatchUtil;
import gateway.model.request.LoginRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 顺序：1
 * 获取前端传过来的用户名和密码
 *
 * @author 米泽鹏
 * @since 2021-08-05 2:26 下午
 */
@Component
@Slf4j
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

	/**
	 * @param authenticationManager              认证管理器
	 * @param customAuthenticationSuccessHandler 认证成功处理
	 * @param customAuthenticationFailureHandler 认证失败处理
	 */
	public CustomAuthenticationFilter(CustomAuthenticationManager authenticationManager, CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler, CustomAuthenticationFailureHandler customAuthenticationFailureHandler) {
		super.setAuthenticationManager(authenticationManager);
		super.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
		super.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
		super.setUsernameParameter(SecurityConstants.FORM_USERNAME_KEY);
		super.setPasswordParameter(SecurityConstants.FORM_PASSWORD_KEY);
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		// 记录登录耗时
		Long loginStartTime = StopWatchUtil.LOGIN_START_TIME.get();
		if (loginStartTime == null) {
			loginStartTime = System.currentTimeMillis();
			StopWatchUtil.LOGIN_START_TIME.set(loginStartTime);
		} else {
			log.warn("已存在login计时器，可能导致login接口执行耗时记录不准确");
		}
		if (request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
			UsernamePasswordAuthenticationToken authRequest;
			try {
				MultiReadHttpServletRequest wrappedRequest = new MultiReadHttpServletRequest(request);
				// 将前端传递的数据转换成jsonBean数据格式
				LoginRequest loginRequest = JSONObject.parseObject(wrappedRequest.getBodyJsonStrByJson(wrappedRequest), LoginRequest.class);
				authRequest = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword(), null);
				authRequest.setDetails(authenticationDetailsSource.buildDetails(wrappedRequest));
			} catch (Exception e) {
				throw new AuthenticationServiceException(ExceptionUtil.getSimpleMessage(e));
			}
			return super.getAuthenticationManager().authenticate(authRequest);
		} else {
			return super.attemptAuthentication(request, response);
		}
	}

}
